from PySide6.QtWidgets import (QMainWindow, QWidget, QVBoxLayout, QHBoxLayout,
                              QPushButton, QListWidget, QListWidgetItem, QLabel)
from PySide6.QtCore import Qt, QTimer, QMutex, QMutexLocker
from PySide6.QtGui import QColor
from components.color_trigger import ColorTriggerItem, ColorTriggerItemWidget
from dialogs.color_picker import ColorPickerDialog
from dialogs.trigger_settings import TriggerSettingsDialog
from dialogs.smart_detection_dialog import SmartDetectionDialog
from utils.config_manager import ConfigManager
from PIL import ImageGrab
import pyautogui
import time
import threading
import os
import sys
import logging

# 配置日志
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)

# 全局热键支持
try:
    from pynput import keyboard
    GLOBAL_HOTKEY_AVAILABLE = True
except ImportError:
    GLOBAL_HOTKEY_AVAILABLE = False
    logger.warning("pynput 未安装，全局热键功能不可用")

class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("智能屏幕取色自动扳机")
        self.resize(600, 500)

        # 颜色触发列表
        self.color_triggers = []

        # 配置管理器
        self.config_manager = ConfigManager()

        # 线程安全锁
        self.detection_mutex = QMutex()
        self.triggers_mutex = QMutex()

        # 配置后台运行支持
        self.setup_background_support()

        # 配置全屏应用兼容性
        self.setup_fullscreen_compatibility()

        # 设置中心组件
        central_widget = QWidget()
        self.setCentralWidget(central_widget)

        # 主布局
        main_layout = QVBoxLayout(central_widget)

        # 标题
        title_label = QLabel("颜色触发器列表")
        title_label.setStyleSheet("font-size: 16px; font-weight: bold;")
        main_layout.addWidget(title_label)

        # 按钮区域
        button_layout = QHBoxLayout()
        self.add_btn = QPushButton("新增")
        self.add_btn.clicked.connect(self.add_color_trigger)
        button_layout.addWidget(self.add_btn)

        # 智能检测区域设置按钮
        self.area_btn = QPushButton("智能检测")
        self.area_btn.clicked.connect(self.open_smart_detection_settings)
        self.area_btn.setToolTip("智能设置检测区域，自动避开游戏准星等中心元素")
        button_layout.addWidget(self.area_btn)

        # 性能监控按钮
        self.perf_btn = QPushButton("性能监控")
        self.perf_btn.clicked.connect(self.open_performance_monitor)
        self.perf_btn.setToolTip("查看实时性能指标和系统资源使用情况")
        button_layout.addWidget(self.perf_btn)

        # 检测区域配置按钮
        self.detection_config_btn = QPushButton("检测区域配置")
        self.detection_config_btn.clicked.connect(self.open_detection_area_config)
        self.detection_config_btn.setToolTip("配置所有触发器的检测区域大小、位置和方法")
        button_layout.addWidget(self.detection_config_btn)

        button_layout.addStretch()
        main_layout.addLayout(button_layout)

        # 列表区域
        self.list_widget = QListWidget()
        self.list_widget.setSpacing(2)
        main_layout.addWidget(self.list_widget)

        # 状态区域
        status_layout = QHBoxLayout()
        self.status_label = QLabel("就绪")
        status_layout.addWidget(self.status_label)
        status_layout.addStretch()
        main_layout.addLayout(status_layout)

        # 检测状态 - 使用独立线程避免UI阻塞
        self.detection_thread = None
        self.detection_running = False

        # 性能优化相关
        self.detection_interval = 0.1  # 初始检测间隔100ms
        self.performance_stats = {
            'avg_detection_time': 0.1,
            'cpu_usage': 0,
            'last_adjustment_time': time.time()
        }

        self.start_detection_thread()

        # 启动时加载配置
        self.load_configs_on_startup()

    def start_detection_thread(self):
        """启动独立的检测线程，避免UI阻塞"""
        with QMutexLocker(self.detection_mutex):
            if self.detection_running:
                return

            logger.info("启动独立检测线程...")
            self.detection_running = True

            def detection_worker():
                """检测工作线程 - 在后台运行，不阻塞UI"""
                logger.info("检测线程开始运行")

                while self.detection_running:
                    try:
                        start_time = time.time()

                        # 线程安全地获取活跃触发器
                        with QMutexLocker(self.triggers_mutex):
                            active_triggers = [item for item in self.color_triggers
                                             if item.detecting and item.enabled]

                        if active_triggers:
                            # 在后台线程中进行颜色检测
                            self.check_colors_background(active_triggers)

                        # 计算检测耗时并动态调整间隔
                        detection_time = time.time() - start_time
                        self.adjust_detection_interval(detection_time, len(active_triggers))

                        # 使用动态间隔休眠
                        time.sleep(self.detection_interval)

                    except Exception as e:
                        logger.error(f"检测线程异常: {e}")
                        # 发生异常时短暂休眠后继续
                        time.sleep(0.5)

                logger.info("检测线程结束")

            self.detection_thread = threading.Thread(target=detection_worker, daemon=True)
            self.detection_thread.start()
            logger.info("检测线程启动成功")

    def stop_detection_thread(self):
        """停止检测线程"""
        with QMutexLocker(self.detection_mutex):
            if not self.detection_running:
                return

            logger.info("停止检测线程...")
            self.detection_running = False

            if self.detection_thread and self.detection_thread.is_alive():
                self.detection_thread.join(timeout=1.0)
                if self.detection_thread.is_alive():
                    logger.warning("检测线程未能及时停止")
                else:
                    logger.info("检测线程已停止")

    def adjust_detection_interval(self, detection_time, active_trigger_count):
        """动态调整检测间隔以优化性能"""
        try:
            current_time = time.time()

            # 更新平均检测时间
            self.performance_stats['avg_detection_time'] = (
                self.performance_stats['avg_detection_time'] * 0.8 + detection_time * 0.2
            )

            # 每5秒调整一次间隔
            if current_time - self.performance_stats['last_adjustment_time'] > 5:
                avg_time = self.performance_stats['avg_detection_time']

                # 根据检测耗时和触发器数量调整间隔
                if avg_time > 0.05:  # 检测耗时超过50ms
                    self.detection_interval = min(0.2, self.detection_interval * 1.2)
                elif avg_time < 0.02 and active_trigger_count > 0:  # 检测很快且有活跃触发器
                    self.detection_interval = max(0.05, self.detection_interval * 0.9)

                # 根据触发器数量调整
                if active_trigger_count > 3:
                    self.detection_interval = max(0.1, self.detection_interval)
                elif active_trigger_count == 0:
                    self.detection_interval = 0.5  # 无活跃触发器时降低频率

                self.performance_stats['last_adjustment_time'] = current_time
                logger.debug(f"调整检测间隔: {self.detection_interval:.3f}s, 平均检测时间: {avg_time:.3f}s")

        except Exception as e:
            logger.error(f"调整检测间隔失败: {e}")

    def check_colors_background(self, active_triggers):
        """后台线程中的颜色检测（不阻塞UI）"""
        try:
            triggered_count = 0
            color_matched_count = 0

            for item in active_triggers:
                # 检查线程是否应该继续运行
                if not self.detection_running:
                    break

                # 获取该触发器的检测位置
                detection_x, detection_y = self.get_detection_position(item)
                if detection_x is None or detection_y is None:
                    continue

                # 根据检测方法选择不同的颜色获取方式
                detection_method = getattr(item, 'detection_method', 'traditional')

                if detection_method == 'dominant_kmeans':
                    # 使用主要颜色检测方法
                    try:
                        color_matches = self.check_dominant_color_match(item, detection_x, detection_y)
                        logger.debug(f"主要颜色检测结果: {color_matches}")
                    except Exception as e:
                        logger.error(f"主要颜色检测失败: {e}")
                        # 回退到传统方法
                        current_color, image_region = self.get_smart_detection_area_color_with_region(item, detection_x, detection_y)
                        if current_color is None:
                            continue
                        color_matches = self.is_color_match(current_color, item, image_region)
                else:
                    # 传统方法：获取检测区域的颜色和图像数据
                    current_color, image_region = self.get_smart_detection_area_color_with_region(item, detection_x, detection_y)
                    if current_color is None:
                        continue
                    # 检查颜色是否匹配（传递图像区域用于高级检测）
                    color_matches = self.is_color_match(current_color, item, image_region)

                if color_matches:
                    color_matched_count += 1
                    item.color_detected = True

                    # 如果热键被按下且颜色匹配，立即触发
                    if getattr(item, 'hotkey_pressed', False):
                        print(f"🎯 热键按下 + 颜色匹配: {item.name} - 立即触发！")

                        # 检查是否已经在持续触发中
                        if not hasattr(item, 'continuous_thread') or not item.continuous_thread or not item.continuous_thread.is_alive():
                            print(f"首次触发，执行第一次点击并启动持续触发")
                            self.execute_mouse_left_click(item)
                            self.start_continuous_clicking_thread(item)

                        triggered_count += 1
                else:
                    item.color_detected = False

            # 使用信号更新UI状态（线程安全）
            self.update_status_from_background(triggered_count, color_matched_count, active_triggers)

        except Exception as e:
            print(f"❌ 后台颜色检测异常: {e}")

    def update_status_from_background(self, triggered_count, color_matched_count, active_triggers):
        """从后台线程安全地更新UI状态"""
        def update_ui():
            try:
                # 更新状态显示
                if triggered_count > 0:
                    self.status_label.setText(f"触发了 {triggered_count} 个动作")
                elif color_matched_count > 0:
                    pressed_count = sum(1 for item in active_triggers if getattr(item, 'hotkey_pressed', False))
                    self.status_label.setText(f"颜色匹配: {color_matched_count} 个, 热键按下: {pressed_count} 个")
                else:
                    pressed_count = sum(1 for item in active_triggers if getattr(item, 'hotkey_pressed', False))
                    if pressed_count > 0:
                        self.status_label.setText(f"热键按下: {pressed_count} 个, 等待颜色出现...")
                    else:
                        self.status_label.setText(f"正在检测: {len(active_triggers)} 个颜色 - 按住热键并等待颜色")
            except Exception as e:
                print(f"❌ UI更新异常: {e}")

        # 使用QTimer.singleShot确保在主线程中执行UI更新
        QTimer.singleShot(0, update_ui)

    def setup_background_support(self):
        """配置后台运行支持"""
        try:
            logger.info("配置后台运行支持...")

            # 禁用 pyautogui 的安全机制，允许后台操作
            pyautogui.FAILSAFE = False  # 禁用鼠标移动到左上角的安全退出
            pyautogui.PAUSE = 0.01  # 减少操作间隔，提高响应速度

            logger.info("后台运行支持配置完成")
            logger.info("- 禁用了 pyautogui 安全机制")
            logger.info("- 设置了更快的操作间隔")
            logger.info("- 程序现在可以在后台运行")

        except Exception as e:
            logger.error(f"配置后台运行支持失败: {e}")

    def setup_fullscreen_compatibility(self):
        """配置全屏应用兼容性"""
        try:
            print("🎮 配置全屏应用兼容性...")

            import sys
            import os

            # Windows 平台特殊配置
            if sys.platform.startswith('win'):
                try:
                    # 尝试提升进程权限
                    import ctypes
                    if ctypes.windll.shell32.IsUserAnAdmin():
                        print("✅ 程序以管理员权限运行")
                    else:
                        print("⚠️ 程序未以管理员权限运行，可能影响全屏应用兼容性")
                        print("   建议：以管理员身份运行程序以获得最佳兼容性")
                except Exception as e:
                    print(f"权限检查失败: {e}")

                # 设置进程优先级
                try:
                    import psutil
                    current_process = psutil.Process()
                    current_process.nice(psutil.HIGH_PRIORITY_CLASS)
                    print("✅ 设置高优先级成功")
                except ImportError:
                    print("⚠️ psutil 未安装，跳过进程优先级设置")
                except Exception as e:
                    print(f"设置优先级失败: {e}")

            print("✅ 全屏应用兼容性配置完成")

        except Exception as e:
            print(f"❌ 配置全屏应用兼容性失败: {e}")

    def get_screen_color_safe(self, x, y):
        """安全的屏幕颜色获取方法（支持后台运行）"""
        try:
            # 边界检查
            screen_width, screen_height = pyautogui.size()
            if not (0 <= x < screen_width and 0 <= y < screen_height):
                logger.warning(f"坐标超出屏幕范围: ({x}, {y})")
                return None

            # 方法1：使用 PIL.ImageGrab（最可靠，支持后台）
            try:
                # 只截取需要的小区域，提高性能
                bbox = (max(0, x-1), max(0, y-1),
                       min(screen_width, x+2), min(screen_height, y+2))
                screenshot = ImageGrab.grab(bbox=bbox)
                if screenshot:
                    # 计算相对坐标
                    rel_x = min(1, x - bbox[0])
                    rel_y = min(1, y - bbox[1])
                    color = screenshot.getpixel((rel_x, rel_y))
                    return color
            except Exception as e:
                logger.debug(f"PIL.ImageGrab 方法失败: {e}")

            # 方法2：使用 pyautogui（备用方法）
            try:
                color = pyautogui.pixel(x, y)
                return color
            except Exception as e:
                logger.debug(f"pyautogui.pixel 方法失败: {e}")

            # 如果都失败了，返回 None
            logger.warning(f"无法获取屏幕颜色 ({x}, {y})")
            return None

        except Exception as e:
            logger.error(f"获取屏幕颜色时发生错误: {e}")
            return None

    def perform_safe_click(self, x=None, y=None, button='left'):
        """安全的鼠标点击方法（支持后台运行）"""
        try:
            # 如果没有指定坐标，使用当前鼠标位置
            if x is None or y is None:
                current_x, current_y = pyautogui.position()
                x = x or current_x
                y = y or current_y

            print(f"🖱️ 执行后台安全点击: ({x}, {y}), 按钮: {button}")

            # 使用 pyautogui 执行点击（已配置为支持后台）
            pyautogui.click(x, y, button=button)

            return True

        except Exception as e:
            print(f"后台安全点击失败: {e}")
            return False

    def get_detection_position(self, trigger_item):
        """获取触发器的检测位置"""
        try:
            detection_mode = getattr(trigger_item, 'detection_mode', 'smart_around_center')

            if detection_mode == "smart_around_center":
                # 智能中心周围检测
                return self.calculate_smart_detection_area(trigger_item)
            elif detection_mode == "center":
                # 传统屏幕中心
                screen_width, screen_height = pyautogui.size()
                return screen_width // 2, screen_height // 2
            else:
                # 默认使用智能检测
                return self.calculate_smart_detection_area(trigger_item)

        except Exception as e:
            print(f"获取检测位置失败: {e}")
            return None, None

    def calculate_smart_detection_area(self, trigger_item):
        """计算智能检测区域的中心坐标"""
        try:
            screen_width, screen_height = pyautogui.size()
            center_x, center_y = screen_width // 2, screen_height // 2

            # 获取配置参数
            offset_x = getattr(trigger_item, 'detection_offset_x', 30)
            offset_y = getattr(trigger_item, 'detection_offset_y', 30)
            width = getattr(trigger_item, 'detection_area_width', 20)
            height = getattr(trigger_item, 'detection_area_height', 20)
            position = getattr(trigger_item, 'detection_position', 'top_right')

            # 根据位置计算检测区域
            if position == "top_right":
                detection_x = center_x + offset_x + width // 2
                detection_y = center_y - offset_y - height // 2
            elif position == "top_left":
                detection_x = center_x - offset_x - width // 2
                detection_y = center_y - offset_y - height // 2
            elif position == "bottom_right":
                detection_x = center_x + offset_x + width // 2
                detection_y = center_y + offset_y + height // 2
            elif position == "bottom_left":
                detection_x = center_x - offset_x - width // 2
                detection_y = center_y + offset_y + height // 2
            else:  # auto 或其他，默认右上角
                detection_x = center_x + offset_x + width // 2
                detection_y = center_y - offset_y - height // 2

            return detection_x, detection_y

        except Exception as e:
            print(f"计算智能检测区域失败: {e}")
            # 回退到屏幕中心
            screen_width, screen_height = pyautogui.size()
            return screen_width // 2, screen_height // 2

    def get_detection_area_color(self, center_x, center_y, area_size):
        """获取检测区域的颜色（支持单点或区域平均）"""
        try:
            if area_size <= 1:
                # 单点检测
                return self.get_screen_color_safe(center_x, center_y)
            else:
                # 区域检测，计算平均颜色
                half_size = area_size // 2
                colors = []

                for dx in range(-half_size, half_size + 1):
                    for dy in range(-half_size, half_size + 1):
                        x = center_x + dx
                        y = center_y + dy
                        color = self.get_screen_color_safe(x, y)
                        if color:
                            colors.append(color)

                if not colors:
                    return None

                # 计算平均颜色
                avg_r = sum(c[0] for c in colors) // len(colors)
                avg_g = sum(c[1] for c in colors) // len(colors)
                avg_b = sum(c[2] for c in colors) // len(colors)

                return (avg_r, avg_g, avg_b)

        except Exception as e:
            print(f"获取检测区域颜色失败: {e}")
            return None

    def get_smart_detection_area_color(self, trigger_item, center_x, center_y):
        """获取智能检测区域的颜色（优化版本 - 支持缓存和采样优化）"""
        try:
            detection_mode = getattr(trigger_item, 'detection_mode', 'smart_around_center')

            if detection_mode == "smart_around_center":
                # 智能矩形区域检测
                width = getattr(trigger_item, 'detection_area_width', 20)
                height = getattr(trigger_item, 'detection_area_height', 20)

                # 计算矩形区域边界
                half_width = width // 2
                half_height = height // 2
                left = max(0, center_x - half_width)
                right = center_x + half_width
                top = max(0, center_y - half_height)
                bottom = center_y + half_height

                # 边界检查
                screen_width, screen_height = pyautogui.size()
                right = min(screen_width - 1, right)
                bottom = min(screen_height - 1, bottom)

                # 优化1：使用PIL截取整个区域，然后处理
                try:
                    bbox = (left, top, right + 1, bottom + 1)
                    screenshot = ImageGrab.grab(bbox=bbox)
                    if screenshot:
                        # 优化2：智能采样 - 根据区域大小调整采样密度
                        area_size = width * height
                        if area_size > 400:  # 大区域使用稀疏采样
                            sample_step = 3
                        elif area_size > 100:  # 中等区域使用中等采样
                            sample_step = 2
                        else:  # 小区域使用密集采样
                            sample_step = 1

                        # 获取采样像素颜色
                        pixels = []
                        img_width, img_height = screenshot.size
                        for y in range(0, img_height, sample_step):
                            for x in range(0, img_width, sample_step):
                                if x < img_width and y < img_height:
                                    pixels.append(screenshot.getpixel((x, y)))

                        if pixels:
                            # 优化3：使用numpy加速计算（如果可用）
                            try:
                                import numpy as np
                                pixel_array = np.array(pixels)
                                avg_color = np.mean(pixel_array, axis=0).astype(int)
                                avg_r, avg_g, avg_b = avg_color
                            except ImportError:
                                # 回退到普通计算
                                avg_r = sum(p[0] for p in pixels) // len(pixels)
                                avg_g = sum(p[1] for p in pixels) // len(pixels)
                                avg_b = sum(p[2] for p in pixels) // len(pixels)

                            logger.debug(f"智能检测区域 ({left},{top})-({right},{bottom}) 平均颜色: RGB({avg_r},{avg_g},{avg_b}), 采样点数: {len(pixels)}")
                            return (avg_r, avg_g, avg_b)
                except Exception as e:
                    logger.debug(f"区域截图失败，回退到逐点检测: {e}")

                # 回退方案：优化的逐点检测
                colors = []
                step = max(1, min(width, height) // 3)  # 优化采样步长
                for x in range(left, right + 1, step):
                    for y in range(top, bottom + 1, step):
                        color = self.get_screen_color_safe(x, y)
                        if color:
                            colors.append(color)

                if not colors:
                    return None

                # 计算平均颜色
                avg_r = sum(c[0] for c in colors) // len(colors)
                avg_g = sum(c[1] for c in colors) // len(colors)
                avg_b = sum(c[2] for c in colors) // len(colors)

                return (avg_r, avg_g, avg_b)
            else:
                # 传统单点检测
                return self.get_screen_color_safe(center_x, center_y)

        except Exception as e:
            logger.error(f"获取智能检测区域颜色失败: {e}")
            return None

    def get_smart_detection_area_color_with_region(self, trigger_item, center_x, center_y):
        """获取智能检测区域的颜色和图像数据（用于高级检测）"""
        try:
            detection_mode = getattr(trigger_item, 'detection_mode', 'smart_around_center')

            if detection_mode == "smart_around_center":
                # 智能矩形区域检测
                width = getattr(trigger_item, 'detection_area_width', 20)
                height = getattr(trigger_item, 'detection_area_height', 20)

                # 计算矩形区域边界
                half_width = width // 2
                half_height = height // 2
                left = max(0, center_x - half_width)
                right = center_x + half_width
                top = max(0, center_y - half_height)
                bottom = center_y + half_height

                # 边界检查
                screen_width, screen_height = pyautogui.size()
                right = min(screen_width - 1, right)
                bottom = min(screen_height - 1, bottom)

                # 截取整个区域
                try:
                    bbox = (left, top, right + 1, bottom + 1)
                    screenshot = ImageGrab.grab(bbox=bbox)
                    if screenshot:
                        # 获取像素数据
                        pixels = list(screenshot.getdata())

                        if pixels:
                            # 计算平均颜色
                            try:
                                import numpy as np
                                pixel_array = np.array(pixels)
                                avg_color = np.mean(pixel_array, axis=0).astype(int)
                                avg_r, avg_g, avg_b = avg_color
                            except ImportError:
                                # 回退到普通计算
                                avg_r = sum(p[0] for p in pixels) // len(pixels)
                                avg_g = sum(p[1] for p in pixels) // len(pixels)
                                avg_b = sum(p[2] for p in pixels) // len(pixels)

                            logger.debug(f"智能检测区域 ({left},{top})-({right},{bottom}) 平均颜色: RGB({avg_r},{avg_g},{avg_b}), 像素数: {len(pixels)}")
                            return (avg_r, avg_g, avg_b), pixels

                except Exception as e:
                    logger.debug(f"区域截图失败，回退到逐点检测: {e}")

                # 回退方案：逐点检测
                colors = []
                step = max(1, min(width, height) // 3)
                for x in range(left, right + 1, step):
                    for y in range(top, bottom + 1, step):
                        color = self.get_screen_color_safe(x, y)
                        if color:
                            colors.append(color)

                if colors:
                    # 计算平均颜色
                    avg_r = sum(c[0] for c in colors) // len(colors)
                    avg_g = sum(c[1] for c in colors) // len(colors)
                    avg_b = sum(c[2] for c in colors) // len(colors)
                    return (avg_r, avg_g, avg_b), colors
                else:
                    return None, None
            else:
                # 传统单点检测
                color = self.get_screen_color_safe(center_x, center_y)
                return color, [color] if color else None

        except Exception as e:
            logger.error(f"获取智能检测区域颜色和图像数据失败: {e}")
            return None, None

    def check_dominant_color_match(self, trigger_item, center_x, center_y):
        """
        使用主要颜色检测方法检查颜色匹配
        基于test5.py的思路，使用K-Means提取主要颜色进行匹配
        """
        try:
            # 懒加载主要颜色检测器
            if not hasattr(self, '_dominant_detector'):
                from utils.dominant_color_detector import DominantColorDetector
                # 根据触发器配置创建检测器
                region_size = getattr(trigger_item, 'dominant_region_size', 200)
                k_clusters = getattr(trigger_item, 'kmeans_clusters', 3)
                self._dominant_detector = DominantColorDetector(
                    region_size=region_size,
                    k_clusters=k_clusters,
                    cache_duration=0.01  # 10ms缓存，更快响应
                )

            # 强制清除缓存以确保实时检测
            self._dominant_detector.clear_cache()

            # 获取目标颜色和容差
            target_color = trigger_item.color
            tolerance = trigger_item.tolerance

            # 获取检测区域大小和偏移
            region_size = getattr(trigger_item, 'dominant_region_size', 200)
            offset_x = getattr(trigger_item, 'dominant_center_offset_x', 0)
            offset_y = getattr(trigger_item, 'dominant_center_offset_y', 0)

            # 计算实际检测中心点
            screen_width, screen_height = pyautogui.size()
            screen_center_x, screen_center_y = screen_width // 2, screen_height // 2
            actual_center_x = screen_center_x + offset_x
            actual_center_y = screen_center_y + offset_y

            # 执行主要颜色匹配检测
            is_match, confidence, detection_info = self._dominant_detector.is_color_match_dominant(
                target_color=target_color,
                tolerance=tolerance,
                center_x=actual_center_x,
                center_y=actual_center_y,
                region_size=region_size
            )

            # 记录检测信息到触发器
            if not hasattr(trigger_item, 'last_detection_info'):
                trigger_item.last_detection_info = {}

            trigger_item.last_detection_info.update({
                'method': 'dominant_kmeans',
                'confidence': confidence,
                'detection_info': detection_info,
                'target_color': target_color,
                'tolerance': tolerance
            })

            # 详细日志
            if detection_info.get('dominant_color'):
                dominant_color = detection_info['dominant_color']
                color_distance = detection_info.get('color_distance', 0)
                logger.debug(f"主要颜色检测: 目标={target_color}, 检测到={dominant_color}, 距离={color_distance:.1f}, 匹配={is_match}, 置信度={confidence:.3f}")

            return is_match

        except ImportError:
            logger.warning("主要颜色检测器不可用，回退到传统方法")
            # 回退到传统检测方法
            current_color, image_region = self.get_smart_detection_area_color_with_region(trigger_item, center_x, center_y)
            if current_color is None:
                return False
            return self.is_color_match(current_color, trigger_item, image_region)
        except Exception as e:
            logger.error(f"主要颜色检测失败: {e}")
            return False



    def add_color_trigger(self):
        """添加新的颜色触发器"""
        dialog = ColorPickerDialog(self)
        if dialog.exec():
            color_data = dialog.get_color_data()

            # 创建新的触发项
            name = f"颜色 #{len(self.color_triggers) + 1}"
            item = ColorTriggerItem(
                name=name,
                color=color_data["color"],
                algorithm=color_data["algorithm"],
                tolerance=color_data.get("tolerance", 10),
                hsv_tolerances=color_data.get("tolerances")
            )

            # 默认使用传统检测方法
            item.detection_method = "traditional"

            # 添加调试信息
            print(f"添加新颜色: {name}, RGB: {color_data['color']}, 算法: {color_data['algorithm']}")

            self.color_triggers.append(item)
            self.update_list()  # 确保这里调用了update_list

    def edit_color_trigger(self, index):
        """编辑颜色触发器"""
        if 0 <= index < len(self.color_triggers):
            item = self.color_triggers[index]

            # 准备初始颜色
            initial_color = QColor(*item.color)
            print(f"编辑颜色触发器: 索引={index}, 原始颜色={item.color}, QColor={initial_color.name()}")

            dialog = ColorPickerDialog(self, initial_color)

            # 设置初始算法和参数
            dialog.algorithm = item.algorithm  # 先设置算法
            if item.algorithm == "HSV":
                dialog.algorithm_combo.setCurrentIndex(1)
                dialog.hsv_tolerances = item.hsv_tolerances
                dialog.setup_hsv_params()
            else:
                dialog.algorithm_combo.setCurrentIndex(0)
                dialog.tolerance = item.tolerance
                dialog.setup_rgb_params()



            # 重要：更新所有颜色预览以显示初始颜色
            dialog.update_color_preview()

            if dialog.exec():
                color_data = dialog.get_color_data()

                # 更新触发项
                item.color = color_data["color"]
                item.algorithm = color_data["algorithm"]

                if item.algorithm == "RGB":
                    item.tolerance = color_data["tolerance"]
                else:
                    item.hsv_tolerances = color_data["tolerances"]



                self.update_list()

    def delete_color_trigger(self, index):
        """删除颜色触发器"""
        if 0 <= index < len(self.color_triggers):
            del self.color_triggers[index]
            self.update_list()

    def open_trigger_settings(self, index):
        """打开触发器设置对话框（快捷键、触发模式等）"""
        if 0 <= index < len(self.color_triggers):
            item = self.color_triggers[index]
            dialog = TriggerSettingsDialog(item, self)

            if dialog.exec():
                settings = dialog.get_settings()

                # 更新触发器设置
                item.trigger_mode = settings["trigger_mode"]
                item.trigger_key = settings["trigger_key"]
                item.trigger_count = settings["trigger_count"]
                item.trigger_interval = settings["trigger_interval"]
                item.current_trigger_count = 0  # 重置触发计数

                print(f"更新触发器设置: {item.name}, 模式: {item.trigger_mode}, 按键: {item.trigger_key}, 次数: {item.trigger_count}, 间隔: {item.trigger_interval}ms")
                self.status_label.setText(f"已更新 {item.name} 的触发器设置")

    def open_detection_area_settings(self, index):
        """打开检测区域设置对话框（区域大小、检测方法等）"""
        if 0 <= index < len(self.color_triggers):
            item = self.color_triggers[index]

            try:
                from dialogs.detection_area_settings import DetectionAreaSettingsDialog
                dialog = DetectionAreaSettingsDialog(item, self)

                if dialog.exec():
                    print(f"更新检测区域设置: {item.name}")
                    print(f"  检测方法: {item.detection_method}")
                    print(f"  区域大小: {getattr(item, 'dominant_region_size', 200)}")
                    print(f"  聚类数量: {item.kmeans_clusters}")
                    print(f"  容差: {item.tolerance}")
                    print(f"  偏移: ({getattr(item, 'dominant_center_offset_x', 0)}, {getattr(item, 'dominant_center_offset_y', 0)})")

                    # 清除检测器缓存，使新设置生效
                    if hasattr(self, '_dominant_detector'):
                        delattr(self, '_dominant_detector')

                    self.status_label.setText(f"已更新 {item.name} 的检测区域设置")

            except ImportError as e:
                self.status_label.setText(f"检测区域设置功能不可用: {e}")
            except Exception as e:
                self.status_label.setText(f"打开检测区域设置失败: {e}")

    def open_smart_detection_settings(self):
        """打开智能检测区域设置对话框"""
        if not self.color_triggers:
            self.status_label.setText("请先添加颜色触发器")
            return

        # 如果只有一个触发器，直接设置
        if len(self.color_triggers) == 1:
            item = self.color_triggers[0]
            dialog = SmartDetectionDialog(item, self)
            if dialog.exec():
                print(f"智能检测区域设置已更新: {item.name}")
                self.status_label.setText(f"已更新 {item.name} 的智能检测区域")
        else:
            # 多个触发器时，让用户选择或应用到所有
            from PySide6.QtWidgets import QMessageBox, QInputDialog

            # 创建选择列表
            items = [f"{i+1}. {item.name}" for i, item in enumerate(self.color_triggers)]
            items.append("应用到所有触发器")

            choice, ok = QInputDialog.getItem(
                self, "选择触发器",
                "请选择要设置智能检测区域的触发器:",
                items, 0, False
            )

            if ok and choice:
                if choice == "应用到所有触发器":
                    # 使用第一个触发器作为模板
                    template_item = self.color_triggers[0]
                    dialog = SmartDetectionDialog(template_item, self)
                    if dialog.exec():
                        settings = dialog.get_settings()
                        # 应用到所有触发器
                        for item in self.color_triggers:
                            item.detection_mode = settings['detection_mode']
                            item.detection_offset_x = settings['detection_offset_x']
                            item.detection_offset_y = settings['detection_offset_y']
                            item.detection_area_width = settings['detection_area_width']
                            item.detection_area_height = settings['detection_area_height']
                            item.detection_position = settings['detection_position']
                        print(f"智能检测区域设置已应用到所有 {len(self.color_triggers)} 个触发器")
                        self.status_label.setText(f"已更新所有触发器的智能检测区域")
                else:
                    # 选择特定触发器
                    index = int(choice.split('.')[0]) - 1
                    if 0 <= index < len(self.color_triggers):
                        item = self.color_triggers[index]
                        dialog = SmartDetectionDialog(item, self)
                        if dialog.exec():
                            print(f"智能检测区域设置已更新: {item.name}")
                            self.status_label.setText(f"已更新 {item.name} 的智能检测区域")

    def open_performance_monitor(self):
        """打开性能监控对话框"""
        try:
            from dialogs.performance_monitor_dialog import PerformanceMonitorDialog
            dialog = PerformanceMonitorDialog(self, self)
            dialog.show()  # 使用show()而不是exec()，允许非模态显示
        except ImportError as e:
            self.status_label.setText(f"性能监控功能不可用: {e}")
        except Exception as e:
            self.status_label.setText(f"打开性能监控失败: {e}")

    def open_detection_area_config(self):
        """打开检测区域配置对话框"""
        try:
            from dialogs.detection_area_config_dialog import DetectionAreaConfigDialog
            dialog = DetectionAreaConfigDialog(self.color_triggers, self)
            if dialog.exec():
                # 配置已更新，清除检测器缓存
                if hasattr(self, '_dominant_detector'):
                    delattr(self, '_dominant_detector')
                self.status_label.setText("检测区域配置已更新")
                print("检测区域配置已保存并应用")
        except ImportError as e:
            self.status_label.setText(f"检测区域配置功能不可用: {e}")
        except Exception as e:
            self.status_label.setText(f"打开检测区域配置失败: {e}")
            import traceback
            traceback.print_exc()

    def update_list(self):
        """更新列表显示"""
        self.list_widget.clear()

        for i, item in enumerate(self.color_triggers):
            list_item = QListWidgetItem()
            item_widget = ColorTriggerItemWidget(item, i)

            # 连接信号
            item_widget.editClicked.connect(self.edit_color_trigger)
            item_widget.deleteClicked.connect(self.delete_color_trigger)
            item_widget.settingsClicked.connect(self.open_trigger_settings)
            item_widget.enabledChanged.connect(self.on_item_enabled_changed)
            item_widget.detectingChanged.connect(self.on_item_detecting_changed)

            # 确保设置了足够的大小
            item_widget.adjustSize()  # 先调整组件大小
            size_hint = item_widget.sizeHint()
            # 确保高度足够
            if size_hint.height() < 60:
                size_hint.setHeight(60)
            list_item.setSizeHint(size_hint)

            self.list_widget.addItem(list_item)
            self.list_widget.setItemWidget(list_item, item_widget)

        # 添加调试信息
        print(f"更新列表: {len(self.color_triggers)} 个项目")

    def on_item_enabled_changed(self, index, enabled):
        """处理项启用状态变化"""
        if 0 <= index < len(self.color_triggers):
            self.color_triggers[index].enabled = enabled

    def on_item_detecting_changed(self, index, detecting):
        """处理项检测状态变化（改进版本 - 更好的状态管理）"""
        if 0 <= index < len(self.color_triggers):
            item = self.color_triggers[index]
            item.detecting = detecting

            if detecting:
                # 启动检测时立即设置热键监听
                print(f"🚀 启动检测: {item.name}")

                # 重置所有状态
                item.color_detected = False
                item.hotkey_pressed = False
                item.current_trigger_count = 0
                item.last_trigger_time = 0

                # 设置热键监听
                self.setup_hotkey_listener(item)

                print(f"✅ {item.name} 检测已启动，等待热键 {item.trigger_key}")
            else:
                # 停止检测时清理相关状态
                print(f"🛑 停止检测: {item.name}")

                # 清理所有相关资源
                item.color_detected = False
                item.hotkey_pressed = False
                self.cleanup_hotkey_listener(item)

                print(f"✅ {item.name} 检测已停止，资源已清理")

            # 更新状态标签
            if detecting:
                self.status_label.setText(f"正在检测: {item.name} - 按住 {item.trigger_key} 并等待颜色出现")
            else:
                # 检查是否还有其他正在检测的项
                active_detections = [item for item in self.color_triggers if item.detecting]
                if active_detections:
                    active_names = [item.name for item in active_detections]
                    self.status_label.setText(f"正在检测: {', '.join(active_names)}")
                else:
                    self.status_label.setText("就绪")

    # 注释掉未使用的方法，因为它引用了不存在的 self.start_btn
    # def toggle_detection(self):
    #     """切换颜色检测状态"""
    #     self.detecting = not self.detecting
    #
    #     if self.detecting:
    #         if not self.color_triggers:
    #             self.status_label.setText("请先添加颜色触发器")
    #             self.detecting = False
    #             return
    #
    #         # 开始检测
    #         self.start_btn.setText("停止检测")
    #         self.status_label.setText("正在检测中...")
    #         self.detection_timer.start(100)  # 每100ms检测一次
    #     else:
    #         # 停止检测
    #         self.start_btn.setText("开始检测")
    #         self.status_label.setText("就绪")
    #         self.detection_timer.stop()

    # 原来的 check_colors 方法已被后台线程替代，避免UI阻塞
    # def check_colors(self):
    #     """检测屏幕颜色（已废弃 - 使用后台线程替代）"""
    #     pass

    def is_color_match(self, current_color, trigger_item, image_region=None):
        """判断颜色是否匹配触发条件（支持混合检测方法）"""
        try:
            target_color = trigger_item.color

            # 检查是否启用混合检测方法
            detection_method = getattr(trigger_item, 'detection_method', 'traditional')

            if detection_method == 'hybrid' and image_region is not None:
                # 使用混合检测方法
                return self._hybrid_color_match(current_color, target_color, trigger_item, image_region)
            elif detection_method == 'kmeans' and image_region is not None:
                # 使用K-Means检测方法
                return self._kmeans_color_match(target_color, trigger_item, image_region)
            else:
                # 使用传统检测方法
                return self._traditional_color_match(current_color, target_color, trigger_item)

        except Exception as e:
            print(f"颜色匹配计算错误: {e}")
            return False

    def _traditional_color_match(self, current_color, target_color, trigger_item):
        """传统颜色匹配方法"""
        if trigger_item.algorithm == "RGB":
            # RGB欧氏距离计算
            r1, g1, b1 = current_color
            r2, g2, b2 = target_color
            distance = ((r1 - r2) ** 2 + (g1 - g2) ** 2 + (b1 - b2) ** 2) ** 0.5
            return distance <= trigger_item.tolerance
        else:
            # HSV空间比较
            import colorsys

            # 转换为HSV
            r1, g1, b1 = current_color
            h1, s1, v1 = colorsys.rgb_to_hsv(r1/255, g1/255, b1/255)

            r2, g2, b2 = target_color
            h2, s2, v2 = colorsys.rgb_to_hsv(r2/255, g2/255, b2/255)

            # 获取容差
            h_tol = trigger_item.hsv_tolerances["h"] / 360  # 转换为0-1范围
            s_tol = trigger_item.hsv_tolerances["s"] / 100
            v_tol = trigger_item.hsv_tolerances["v"] / 100

            # 色相是循环的，需要特殊处理
            h_diff = min(abs(h1 - h2), 1 - abs(h1 - h2))
            s_diff = abs(s1 - s2)
            v_diff = abs(v1 - v2)

            return h_diff <= h_tol and s_diff <= s_tol and v_diff <= v_tol

    def _hybrid_color_match(self, current_color, target_color, trigger_item, image_region):
        """混合颜色匹配方法"""
        try:
            # 懒加载混合检测器
            if not hasattr(self, '_hybrid_detector'):
                from utils.kmeans_color_detection import HybridColorDetector
                self._hybrid_detector = HybridColorDetector()

            # 获取检测区域像素数据
            if hasattr(image_region, 'getdata'):
                pixels = list(image_region.getdata())
            else:
                pixels = image_region

            # 使用混合检测
            is_match, confidence, method_used = self._hybrid_detector.detect_color_hybrid(
                target_color, pixels, trigger_item.algorithm,
                trigger_item.tolerance, trigger_item.hsv_tolerances
            )

            # 记录检测方法和置信度
            if not hasattr(trigger_item, 'last_detection_info'):
                trigger_item.last_detection_info = {}
            trigger_item.last_detection_info.update({
                'method': method_used,
                'confidence': confidence,
                'pixel_count': len(pixels)
            })

            return is_match

        except ImportError:
            logger.warning("K-Means检测器不可用，回退到传统方法")
            return self._traditional_color_match(current_color, target_color, trigger_item)
        except Exception as e:
            logger.error(f"混合颜色匹配失败: {e}")
            return self._traditional_color_match(current_color, target_color, trigger_item)

    def _kmeans_color_match(self, target_color, trigger_item, image_region):
        """K-Means颜色匹配方法"""
        try:
            # 懒加载K-Means检测器
            if not hasattr(self, '_kmeans_detector'):
                from utils.kmeans_color_detection import KMeansColorDetector
                self._kmeans_detector = KMeansColorDetector(
                    n_clusters=getattr(trigger_item, 'kmeans_clusters', 3),
                    tolerance=trigger_item.tolerance
                )

            # 获取检测区域像素数据
            if hasattr(image_region, 'getdata'):
                pixels = list(image_region.getdata())
            else:
                pixels = image_region

            # 使用K-Means检测
            is_match, confidence = self._kmeans_detector.is_color_match_kmeans(
                target_color, pixels
            )

            # 记录检测信息
            if not hasattr(trigger_item, 'last_detection_info'):
                trigger_item.last_detection_info = {}
            trigger_item.last_detection_info.update({
                'method': 'kmeans',
                'confidence': confidence,
                'pixel_count': len(pixels)
            })

            return is_match

        except ImportError:
            logger.warning("K-Means检测器不可用，回退到传统方法")
            # 计算平均颜色作为回退
            if hasattr(image_region, 'getdata'):
                pixels = list(image_region.getdata())
                if pixels:
                    avg_color = tuple(sum(c[i] for c in pixels) // len(pixels) for i in range(3))
                    return self._traditional_color_match(avg_color, target_color, trigger_item)
            return False
        except Exception as e:
            logger.error(f"K-Means颜色匹配失败: {e}")
            return False

    def execute_trigger_action(self, trigger_item):
        """执行触发动作"""
        try:
            current_time = time.time() * 1000  # 转换为毫秒

            # 检查触发间隔
            if current_time - trigger_item.last_trigger_time < trigger_item.trigger_interval:
                return

            # 检查触发次数限制
            if trigger_item.trigger_count > 0 and trigger_item.current_trigger_count >= trigger_item.trigger_count:
                self.status_label.setText(f"{trigger_item.name} 已达到触发次数限制")
                return

            # 执行触发动作
            self.perform_action(trigger_item.trigger_mode, trigger_item.trigger_key)

            # 更新触发状态
            trigger_item.current_trigger_count += 1
            trigger_item.last_trigger_time = current_time

            # 更新状态显示
            if trigger_item.trigger_count > 0:
                remaining = trigger_item.trigger_count - trigger_item.current_trigger_count
                self.status_label.setText(f"触发 {trigger_item.name} (剩余 {remaining} 次)")
            else:
                self.status_label.setText(f"触发 {trigger_item.name} (第 {trigger_item.current_trigger_count} 次)")

        except Exception as e:
            print(f"执行触发动作错误: {e}")
            self.status_label.setText(f"触发动作执行错误: {str(e)}")

    def perform_action(self, mode, key):
        """执行具体的按键动作"""
        try:
            # 解析快捷键
            parsed_key = self.parse_hotkey(key)

            if parsed_key["mouse_button"]:
                # 鼠标操作（可能包含修饰键）
                self.perform_mouse_action(mode, parsed_key)
            else:
                # 键盘操作
                self.perform_keyboard_action(mode, parsed_key)

        except Exception as e:
            print(f"执行按键动作错误: {e}")
            raise

    def parse_hotkey(self, key):
        """解析快捷键字符串"""
        result = {
            "ctrl": False,
            "shift": False,
            "alt": False,
            "key": "",
            "mouse_button": ""
        }

        if "+" in key:
            parts = key.split("+")
            for part in parts:
                part = part.strip()
                if part.lower() == "ctrl":
                    result["ctrl"] = True
                elif part.lower() == "shift":
                    result["shift"] = True
                elif part.lower() == "alt":
                    result["alt"] = True
                elif part.lower() in ["left", "right", "middle"]:
                    result["mouse_button"] = part.lower()
                else:
                    result["key"] = part
        else:
            # 单个按键
            if key.lower() in ["left", "right", "middle"]:
                result["mouse_button"] = key.lower()
            else:
                result["key"] = key

        return result

    def perform_mouse_action(self, mode, parsed_key):
        """执行鼠标动作"""
        mouse_button = parsed_key["mouse_button"]

        # 先按下修饰键
        modifiers = []
        if parsed_key["ctrl"]:
            modifiers.append("ctrl")
            pyautogui.keyDown("ctrl")
        if parsed_key["shift"]:
            modifiers.append("shift")
            pyautogui.keyDown("shift")
        if parsed_key["alt"]:
            modifiers.append("alt")
            pyautogui.keyDown("alt")

        try:
            # 执行鼠标动作
            if mode == "press":
                pyautogui.mouseDown(button=mouse_button)
            elif mode == "release":
                pyautogui.mouseUp(button=mouse_button)
            elif mode == "click":
                pyautogui.click(button=mouse_button)
        finally:
            # 释放修饰键
            for modifier in reversed(modifiers):
                pyautogui.keyUp(modifier)

    def perform_keyboard_action(self, mode, parsed_key):
        """执行键盘动作"""
        if not parsed_key["key"]:
            return

        # 构建按键列表
        keys = []
        if parsed_key["ctrl"]:
            keys.append("ctrl")
        if parsed_key["shift"]:
            keys.append("shift")
        if parsed_key["alt"]:
            keys.append("alt")
        keys.append(parsed_key["key"].lower())

        if mode == "press":
            for k in keys:
                pyautogui.keyDown(k)
        elif mode == "release":
            for k in reversed(keys):
                pyautogui.keyUp(k)
        elif mode == "click":
            if len(keys) > 1:
                pyautogui.hotkey(*keys)
            else:
                pyautogui.press(keys[0])

    def setup_hotkey_listener(self, trigger_item):
        """为触发器设置全局热键监听（改进版本 - 防止资源泄漏）"""
        if not GLOBAL_HOTKEY_AVAILABLE:
            logger.warning("全局热键功能不可用，跳过热键监听设置")
            return

        # 如果已经有监听器，先清理
        if hasattr(trigger_item, 'hotkey_listener') and trigger_item.hotkey_listener:
            self.cleanup_hotkey_listener(trigger_item)

        try:
            logger.info(f"设置全局热键监听: {trigger_item.trigger_key}")

            # 创建热键状态跟踪
            trigger_item.hotkey_pressed = False
            trigger_item.listener_active = True  # 添加监听器活跃标志

            # 创建键盘事件处理器
            def create_key_handler(is_press_event):
                def handler(key):
                    try:
                        # 检查监听器是否应该继续工作
                        if not getattr(trigger_item, 'listener_active', False):
                            return

                        # 检查触发器是否仍在检测状态
                        if not getattr(trigger_item, 'detecting', False):
                            return

                        # 检查是否是目标热键
                        is_match = self.is_target_key_enhanced(key, trigger_item.trigger_key)

                        if is_match:
                            if is_press_event:
                                if not getattr(trigger_item, 'hotkey_pressed', False):
                                    logger.debug(f"热键按下: {key}")
                                    trigger_item.hotkey_pressed = True
                                    QTimer.singleShot(0, lambda: self.on_trigger_hotkey_pressed(trigger_item))
                            else:
                                if getattr(trigger_item, 'hotkey_pressed', False):
                                    logger.debug(f"热键释放: {key}")
                                    trigger_item.hotkey_pressed = False
                                    QTimer.singleShot(0, lambda: self.on_trigger_hotkey_released(trigger_item))

                    except Exception as e:
                        logger.error(f"按键处理错误: {e}")
                return handler

            # 创建监听器
            listener = keyboard.Listener(
                on_press=create_key_handler(True),
                on_release=create_key_handler(False),
                suppress=False
            )

            # 启动监听器
            listener.start()
            time.sleep(0.05)  # 等待监听器启动

            # 验证监听器状态
            if hasattr(listener, 'running') and listener.running:
                logger.info(f"热键监听器启动成功: {trigger_item.trigger_key}")
                trigger_item.hotkey_listener = listener
            else:
                logger.error("热键监听器启动失败")
                trigger_item.listener_active = False

        except Exception as e:
            logger.error(f"设置热键监听失败: {e}")
            trigger_item.listener_active = False

    def is_target_key_enhanced(self, pressed_key, target_key_string):
        """增强的目标键检查（多重匹配方法）"""
        try:
            if not target_key_string:
                return False

            target_lower = target_key_string.lower().strip()
            print(f"🔍 增强检查: {pressed_key} vs 目标: '{target_lower}'")

            # 方法1: 字符匹配
            if hasattr(pressed_key, 'char') and pressed_key.char:
                char_lower = pressed_key.char.lower()
                if char_lower == target_lower:
                    print(f"✅ 字符匹配成功: '{char_lower}' == '{target_lower}'")
                    return True

            # 方法2: 名称匹配
            if hasattr(pressed_key, 'name'):
                name_lower = pressed_key.name.lower()
                if name_lower == target_lower:
                    print(f"✅ 名称匹配成功: '{name_lower}' == '{target_lower}'")
                    return True

            # 方法3: 字符串表示匹配
            key_str = str(pressed_key).lower()

            # F键特殊处理
            if target_lower.startswith('f') and target_lower[1:].isdigit():
                if f"key.{target_lower}" in key_str:
                    print(f"✅ F键匹配成功: '{key_str}' 包含 'key.{target_lower}'")
                    return True

            # 特殊键匹配
            special_keys = {
                'space': ['key.space', ' '],
                'enter': ['key.enter', 'key.return'],
                'esc': ['key.esc', 'key.escape'],
                'tab': ['key.tab'],
                '`': ['`', 'grave'],
                'backquote': ['`', 'grave'],
                'grave': ['`', 'grave']
            }

            if target_lower in special_keys:
                for pattern in special_keys[target_lower]:
                    if pattern in key_str or pattern == getattr(pressed_key, 'char', ''):
                        print(f"✅ 特殊键匹配成功: '{key_str}' 匹配模式 '{pattern}'")
                        return True

            # 方法4: 直接字符串包含匹配
            if target_lower in key_str:
                print(f"✅ 包含匹配成功: '{key_str}' 包含 '{target_lower}'")
                return True

            print(f"❌ 所有匹配方法都失败")
            return False

        except Exception as e:
            print(f"❌ 增强键检查失败: {e}")
            return False

    def test_hotkey_listener(self, trigger_item):
        """测试热键监听器是否正常工作"""
        try:
            print(f"🧪 测试热键监听器...")
            print(f"   目标热键: {trigger_item.trigger_key}")
            print(f"   监听器对象: {trigger_item.hotkey_listener}")
            print(f"   监听器运行状态: {getattr(trigger_item.hotkey_listener, 'running', '未知')}")

            if hasattr(trigger_item.hotkey_listener, 'running') and trigger_item.hotkey_listener.running:
                print(f"✅ 热键监听器测试通过")
                print(f"💡 现在请按下热键 '{trigger_item.trigger_key}' 进行测试")
                print(f"   如果没有反应，请运行 diagnose_hotkey_issue.py 进行详细诊断")
            else:
                print(f"❌ 热键监听器测试失败")
                print(f"   监听器未正常运行")

        except Exception as e:
            print(f"❌ 测试热键监听器失败: {e}")

    def verify_fullscreen_hotkey_compatibility(self, trigger_item):
        """验证全屏应用热键兼容性"""
        try:
            print(f"🔍 验证全屏应用热键兼容性...")

            # 检查监听器状态
            if hasattr(trigger_item, 'hotkey_listener') and trigger_item.hotkey_listener:
                if trigger_item.hotkey_listener.running:
                    print(f"✅ 热键监听器正常运行")
                else:
                    print(f"⚠️ 热键监听器未运行")

            # 提供全屏应用使用建议
            print(f"💡 全屏应用使用建议:")
            print(f"   1. 确保程序以管理员权限运行")
            print(f"   2. 在全屏应用中测试热键响应")
            print(f"   3. 如果无响应，尝试切换到窗口模式测试")
            print(f"   4. 某些游戏可能需要特殊设置")

        except Exception as e:
            print(f"验证全屏兼容性失败: {e}")

    def cleanup_hotkey_listener(self, trigger_item):
        """清理触发器的热键监听（改进版本 - 防止资源泄漏）"""
        logger.info(f"开始清理 {trigger_item.name} 的热键监听...")

        # 首先设置监听器为非活跃状态
        if hasattr(trigger_item, 'listener_active'):
            trigger_item.listener_active = False

        # 停止持续点击线程
        self.stop_continuous_clicking_thread(trigger_item)

        # 重置热键状态
        trigger_item.hotkey_pressed = False

        # 清理热键监听器
        if hasattr(trigger_item, 'hotkey_listener') and trigger_item.hotkey_listener:
            try:
                logger.debug("停止热键监听器...")
                trigger_item.hotkey_listener.stop()

                # 等待监听器完全停止
                time.sleep(0.1)

                trigger_item.hotkey_listener = None
                logger.info(f"成功清理 {trigger_item.name} 的热键监听")
            except Exception as e:
                logger.error(f"清理热键监听失败: {e}")
                # 强制设置为 None，防止资源泄漏
                trigger_item.hotkey_listener = None
        else:
            logger.debug(f"{trigger_item.name} 没有活跃的热键监听器")

    def convert_to_pynput_format(self, trigger_key):
        """将触发按键转换为 pynput 格式"""
        if not trigger_key:
            return None

        # 处理鼠标按键（pynput 不支持鼠标热键，这里暂时跳过）
        if trigger_key.lower() in ["left", "right", "middle"]:
            print(f"警告: pynput 不支持鼠标热键 {trigger_key}，跳过")
            return None

        try:
            # 处理组合键
            if "+" in trigger_key:
                parts = [part.strip() for part in trigger_key.split("+")]
                pynput_parts = []

                for part in parts:
                    if part.lower() == "ctrl":
                        pynput_parts.append("<ctrl>")
                    elif part.lower() == "shift":
                        pynput_parts.append("<shift>")
                    elif part.lower() == "alt":
                        pynput_parts.append("<alt>")
                    else:
                        # 键盘按键
                        if len(part) == 1:
                            pynput_parts.append(part.lower())
                        else:
                            # 特殊键
                            key_map = {
                                "space": "<space>",
                                "enter": "<enter>",
                                "return": "<enter>",
                                "esc": "<esc>",
                                "escape": "<esc>",
                                "tab": "<tab>",
                                "backspace": "<backspace>",
                                "delete": "<delete>",
                            }
                            # F键
                            if part.lower().startswith("f") and part[1:].isdigit():
                                pynput_parts.append(f"<{part.lower()}>")
                            else:
                                pynput_parts.append(key_map.get(part.lower(), part.lower()))

                return "+".join(pynput_parts)
            else:
                # 单个按键
                if len(trigger_key) == 1:
                    return trigger_key.lower()
                else:
                    # 特殊键处理
                    key_map = {
                        "space": "<space>",
                        "enter": "<enter>",
                        "return": "<enter>",
                        "esc": "<esc>",
                        "escape": "<esc>",
                        "tab": "<tab>",
                        "backspace": "<backspace>",
                        "delete": "<delete>",
                    }
                    if trigger_key.lower().startswith("f") and trigger_key[1:].isdigit():
                        return f"<{trigger_key.lower()}>"
                    return key_map.get(trigger_key.lower(), trigger_key.lower())

        except Exception as e:
            print(f"转换热键格式失败: {e}")
            return None

    def parse_hotkey_for_listener(self, trigger_key):
        """解析热键用于键盘监听器"""
        if not trigger_key:
            return None

        # 处理鼠标按键（不支持）
        if trigger_key.lower() in ["left", "right", "middle"]:
            print(f"警告: 不支持鼠标按键 {trigger_key} 作为触发键")
            return None

        try:
            result = {
                "ctrl": False,
                "shift": False,
                "alt": False,
                "key": None
            }

            if "+" in trigger_key:
                parts = [part.strip() for part in trigger_key.split("+")]
                for part in parts:
                    if part.lower() == "ctrl":
                        result["ctrl"] = True
                    elif part.lower() == "shift":
                        result["shift"] = True
                    elif part.lower() == "alt":
                        result["alt"] = True
                    else:
                        # 主键
                        result["key"] = self.convert_key_name(part)
            else:
                # 单个按键
                result["key"] = self.convert_key_name(trigger_key)

            return result if result["key"] else None

        except Exception as e:
            print(f"解析热键失败: {e}")
            return None

    def convert_key_name(self, key_name):
        """转换按键名称为 pynput Key 对象"""
        try:
            # 单个字符
            if len(key_name) == 1:
                return keyboard.KeyCode.from_char(key_name.lower())

            # 特殊键映射
            key_map = {
                "space": keyboard.Key.space,
                "enter": keyboard.Key.enter,
                "return": keyboard.Key.enter,
                "esc": keyboard.Key.esc,
                "escape": keyboard.Key.esc,
                "tab": keyboard.Key.tab,
                "backspace": keyboard.Key.backspace,
                "delete": keyboard.Key.delete,
                "shift": keyboard.Key.shift,
                "ctrl": keyboard.Key.ctrl,
                "alt": keyboard.Key.alt,
                "up": keyboard.Key.up,
                "down": keyboard.Key.down,
                "left": keyboard.Key.left,
                "right": keyboard.Key.right,
            }

            # F键
            if key_name.lower().startswith("f") and key_name[1:].isdigit():
                f_num = int(key_name[1:])
                if 1 <= f_num <= 12:
                    return getattr(keyboard.Key, f"f{f_num}")

            return key_map.get(key_name.lower())

        except Exception as e:
            print(f"转换按键名称失败: {e}")
            return None

    def is_hotkey_match(self, pressed_key, parsed_hotkey, is_press_event):
        """检查按下的键是否匹配热键组合"""
        try:
            # 简化的热键匹配逻辑
            # 主要检查主键是否匹配（暂时忽略修饰键的精确检查）
            if pressed_key == parsed_hotkey["key"]:
                return True

            # 检查字符键
            if hasattr(pressed_key, 'char') and hasattr(parsed_hotkey["key"], 'char'):
                if pressed_key.char and parsed_hotkey["key"].char:
                    return pressed_key.char.lower() == parsed_hotkey["key"].char.lower()

            return False

        except Exception as e:
            print(f"热键匹配检查失败: {e}")
            return False

    def is_target_key(self, pressed_key, target_key_string):
        """简化的目标键检查"""
        try:
            if not target_key_string:
                print(f"目标键字符串为空")
                return False

            print(f"检查按键: {pressed_key} vs 目标: {target_key_string}")

            # 处理单个字符键
            if len(target_key_string) == 1:
                if hasattr(pressed_key, 'char') and pressed_key.char:
                    result = pressed_key.char.lower() == target_key_string.lower()
                    print(f"字符键匹配: {pressed_key.char} == {target_key_string} -> {result}")
                    return result

            # 处理特殊键
            key_name = target_key_string.lower()

            # 空格键
            if key_name in ['space', ' ']:
                result = pressed_key == keyboard.Key.space
                print(f"空格键匹配: {pressed_key} == Key.space -> {result}")
                return result

            # 回车键
            if key_name in ['enter', 'return']:
                result = pressed_key == keyboard.Key.enter
                print(f"回车键匹配: {pressed_key} == Key.enter -> {result}")
                return result

            # F键
            if key_name.startswith('f') and key_name[1:].isdigit():
                f_num = int(key_name[1:])
                if 1 <= f_num <= 12:
                    target_f_key = getattr(keyboard.Key, f"f{f_num}", None)
                    result = pressed_key == target_f_key
                    print(f"F键匹配: {pressed_key} == {target_f_key} -> {result}")
                    return result

            # Esc键
            if key_name in ['esc', 'escape']:
                result = pressed_key == keyboard.Key.esc
                print(f"Esc键匹配: {pressed_key} == Key.esc -> {result}")
                return result

            # Tab键
            if key_name == 'tab':
                result = pressed_key == keyboard.Key.tab
                print(f"Tab键匹配: {pressed_key} == Key.tab -> {result}")
                return result

            # 暂时忽略组合键的复杂检查，只检查主键
            if '+' in target_key_string:
                parts = target_key_string.split('+')
                main_key = parts[-1].strip()  # 取最后一个作为主键
                print(f"组合键，检查主键: {main_key}")
                return self.is_target_key(pressed_key, main_key)

            print(f"未匹配的按键类型: {target_key_string}")
            return False

        except Exception as e:
            print(f"目标键检查失败: {e}")
            return False

    def on_trigger_hotkey_pressed(self, trigger_item):
        """当用户按下触发热键时执行（新逻辑：只设置状态，等待颜色检测触发）"""
        print(f"=== on_trigger_hotkey_pressed 被调用 ===")
        print(f"trigger_item.color_detected: {trigger_item.color_detected}")
        print(f"trigger_item.hotkey_pressed: {getattr(trigger_item, 'hotkey_pressed', 'undefined')}")

        print(f"用户按下触发热键: {trigger_item.trigger_key}")
        print(f"等待颜色检测循环检测到颜色匹配时自动触发...")

        # 如果当前已经检测到颜色，立即执行第一次点击并启动持续触发
        if trigger_item.color_detected:
            print(f"颜色已匹配，立即执行第一次点击")
            self.execute_mouse_left_click(trigger_item)

            # 启动持续触发线程
            print(f"启动持续触发线程")
            self.start_continuous_clicking_thread(trigger_item)
        else:
            print(f"颜色未匹配，等待颜色出现...")

    def on_trigger_hotkey_released(self, trigger_item):
        """当用户释放触发热键时执行"""
        print(f"=== on_trigger_hotkey_released 被调用 ===")
        print(f"trigger_item.hotkey_pressed: {getattr(trigger_item, 'hotkey_pressed', 'undefined')}")

        # 注意：这里不需要检查 hotkey_pressed 状态，因为在热键监听器中已经检查过了

        print(f"用户释放触发热键: {trigger_item.trigger_key}, 停止持续执行")

        # 停止持续触发线程
        self.stop_continuous_clicking_thread(trigger_item)

    def execute_mouse_left_click(self, trigger_item):
        """执行鼠标左键点击动作"""
        try:
            print(f"=== execute_mouse_left_click 被调用 ===")
            current_time = time.time() * 1000  # 转换为毫秒
            print(f"当前时间: {current_time}, 上次触发时间: {trigger_item.last_trigger_time}")
            print(f"触发间隔: {trigger_item.trigger_interval}ms")

            # 检查触发间隔
            if current_time - trigger_item.last_trigger_time < trigger_item.trigger_interval:
                print(f"触发间隔未到，跳过点击")
                return

            # 检查触发次数限制
            print(f"当前触发次数: {trigger_item.current_trigger_count}, 限制次数: {trigger_item.trigger_count}")
            if trigger_item.trigger_count > 0 and trigger_item.current_trigger_count >= trigger_item.trigger_count:
                print(f"已达到触发次数限制")
                self.status_label.setText(f"{trigger_item.name} 已达到触发次数限制")
                return

            # 执行后台安全的鼠标左键点击
            print(f"执行后台安全鼠标左键点击！")
            success = self.perform_safe_click(button='left')

            if not success:
                print(f"后台安全鼠标左键点击失败")
                self.status_label.setText(f"鼠标点击执行失败")
                return

            print(f"后台安全鼠标左键点击完成")

            # 更新触发状态
            trigger_item.current_trigger_count += 1
            trigger_item.last_trigger_time = current_time

            # 更新状态显示
            if trigger_item.trigger_count > 0:
                remaining = trigger_item.trigger_count - trigger_item.current_trigger_count
                self.status_label.setText(f"触发 {trigger_item.name} - 鼠标左键点击 (剩余 {remaining} 次)")
            else:
                self.status_label.setText(f"触发 {trigger_item.name} - 鼠标左键点击 (第 {trigger_item.current_trigger_count} 次)")

        except Exception as e:
            print(f"执行鼠标左键点击错误: {e}")
            self.status_label.setText(f"鼠标点击执行错误: {str(e)}")

    def start_continuous_clicking_thread(self, trigger_item):
        """启动持续点击线程（改进版本 - 防止线程泄漏）"""
        print(f"=== start_continuous_clicking_thread 被调用 ===")

        # 停止现有的线程（如果有）
        self.stop_continuous_clicking_thread(trigger_item)

        # 重置停止标志
        trigger_item.stop_continuous = False
        trigger_item.thread_active = True  # 添加线程活跃标志

        # 创建并启动新线程
        def continuous_click_worker():
            print(f"持续点击线程开始运行")
            click_count = 0

            try:
                while not trigger_item.stop_continuous and getattr(trigger_item, 'thread_active', False):
                    # 检查基本状态
                    if not getattr(trigger_item, 'hotkey_pressed', False):
                        print(f"热键未按下，停止线程")
                        break

                    if not getattr(trigger_item, 'color_detected', False):
                        print(f"颜色未检测到，停止线程")
                        break

                    if not getattr(trigger_item, 'detecting', False):
                        print(f"检测已停止，停止线程")
                        break

                    # 检查触发次数限制
                    if trigger_item.trigger_count > 0 and trigger_item.current_trigger_count >= trigger_item.trigger_count:
                        print(f"达到触发次数限制，停止线程")
                        QTimer.singleShot(0, lambda: self.status_label.setText(f"{trigger_item.name} 已达到触发次数限制"))
                        break

                    # 执行点击
                    click_count += 1
                    print(f"线程执行点击 #{click_count}")
                    self.execute_mouse_left_click(trigger_item)

                    # 等待间隔时间（使用更小的分片等待，便于快速响应停止信号）
                    interval_seconds = trigger_item.trigger_interval / 1000.0
                    sleep_chunks = max(1, int(interval_seconds * 10))  # 分成10份
                    chunk_time = interval_seconds / sleep_chunks

                    for _ in range(sleep_chunks):
                        if trigger_item.stop_continuous or not getattr(trigger_item, 'thread_active', False):
                            break
                        time.sleep(chunk_time)

            except Exception as e:
                print(f"❌ 持续点击线程异常: {e}")
            finally:
                print(f"持续点击线程结束 (总点击次数: {click_count})")
                trigger_item.thread_active = False

        thread = threading.Thread(target=continuous_click_worker, daemon=True)
        trigger_item.continuous_thread = thread
        thread.start()

        print(f"持续点击线程启动成功")

    def stop_continuous_clicking_thread(self, trigger_item):
        """停止持续点击线程（改进版本 - 更快速的停止）"""
        print(f"=== stop_continuous_clicking_thread 被调用 ===")

        # 设置停止标志
        trigger_item.stop_continuous = True
        if hasattr(trigger_item, 'thread_active'):
            trigger_item.thread_active = False

        # 等待线程结束
        if hasattr(trigger_item, 'continuous_thread') and trigger_item.continuous_thread:
            if trigger_item.continuous_thread.is_alive():
                print(f"等待线程结束...")
                trigger_item.continuous_thread.join(timeout=0.5)  # 减少等待时间到0.5秒
                if trigger_item.continuous_thread.is_alive():
                    print(f"⚠️ 线程未能及时结束，但已设置停止标志")
                else:
                    print(f"✅ 线程已正常结束")
            trigger_item.continuous_thread = None
        else:
            print(f"📝 没有活跃的线程")

        print(f"停止持续点击线程完成")

    def closeEvent(self, event):
        """窗口关闭时清理资源（改进版本 - 包含检测线程清理）"""
        logger.info("程序正在关闭，清理所有资源...")

        try:
            # 停止检测线程
            self.stop_detection_thread()

            # 保存配置文件
            self.save_configs_on_exit()

            # 清理所有热键监听器和持续点击线程
            for item in self.color_triggers:
                self.cleanup_hotkey_listener(item)

            logger.info("资源清理完成")
        except Exception as e:
            logger.error(f"资源清理时发生错误: {e}")
        finally:
            super().closeEvent(event)

    def get_performance_stats(self):
        """获取性能统计信息"""
        stats = {
            'detection_running': self.detection_running,
            'active_triggers': len([item for item in self.color_triggers if item.detecting]),
            'total_triggers': len(self.color_triggers),
            'hotkey_listeners': len([item for item in self.color_triggers
                                   if hasattr(item, 'hotkey_listener') and item.hotkey_listener]),
            'continuous_threads': len([item for item in self.color_triggers
                                     if hasattr(item, 'continuous_thread') and
                                     item.continuous_thread and item.continuous_thread.is_alive()])
        }
        return stats

    def load_configs_on_startup(self):
        """启动时加载配置文件"""
        try:
            print("=" * 50)
            print("启动时加载配置文件...")

            # 显示配置信息
            config_info = self.config_manager.get_config_info()
            print(f"配置目录: {config_info['config_dir']}")
            print(f"配置文件数量: {config_info['file_count']}")

            if config_info['file_count'] > 0:
                print(f"配置文件列表: {', '.join(config_info['files'])}")

                # 加载配置
                loaded_triggers = self.config_manager.load_all_triggers()
                self.color_triggers = loaded_triggers

                # 更新UI
                self.update_list()

                print(f"✅ 成功加载 {len(loaded_triggers)} 个颜色触发器")
                self.status_label.setText(f"已加载 {len(loaded_triggers)} 个颜色规则")
            else:
                print("📁 没有找到配置文件，从空列表开始")
                self.status_label.setText("就绪 - 没有找到配置文件")

        except Exception as e:
            print(f"❌ 加载配置文件失败: {e}")
            self.status_label.setText(f"配置加载失败: {str(e)}")
        finally:
            print("=" * 50)

    def save_configs_on_exit(self):
        """退出时保存配置文件"""
        try:
            print("=" * 50)
            print("退出时保存配置文件...")

            if not self.color_triggers:
                print("📝 没有颜色触发器需要保存")
                return

            # 备份现有配置
            self.config_manager.backup_configs()

            # 保存当前配置
            self.config_manager.save_all_triggers(self.color_triggers)

            print(f"✅ 成功保存 {len(self.color_triggers)} 个颜色触发器")

        except Exception as e:
            print(f"❌ 保存配置文件失败: {e}")
        finally:
            print("=" * 50)
